import argparse
import os
import time
import yaml
import threading
from workers import frame_camera_worker,h264_camera_worker,alive_worker,detect_worker
from workers import notify_worker
from pathlib import Path
from tools.log import logger,setup_logger
from tools.lock.file_lock import FileLock

def validate_file_path(path):
    """验证文件路径是否合法"""
    path = Path(path)
    if not path.exists():
        raise argparse.ArgumentTypeError(f"文件不存在: {path}")
    if not path.is_file():
        raise argparse.ArgumentTypeError(f"路径不是文件: {path}")
    return path

def validate_encoding(encoding):
    """验证编码格式是否有效"""
    try:
        "test".encode(encoding).decode(encoding)
        return encoding
    except LookupError:
        raise argparse.ArgumentTypeError(f"不支持的编码格式: {encoding}")

def parse_args():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    
    parser.add_argument('--global_conf',
                       type=validate_file_path,
                       required=True,
                       help='全局配置文件路径 (必须存在)')
    
    parser.add_argument('--camera_conf',
                       type=validate_file_path,
                       required=True,
                       help='相机配置文件路径 (必须存在)')
    
    parser.add_argument('--conf_encoding',
                       type=validate_encoding,
                       default='utf-8',
                       help='文件编码格式')
    parser.add_argument('--log_file',
                       default=None,
                       help='日志文件')
    return parser.parse_args()

def load_conf(conf_path,conf_encoding):
    with open(conf_path,"r",encoding=conf_encoding) as file:
        return yaml.safe_load(file)    


def save_to(data, file):
    """
    保存字典到 YAML 文件。
    """
    try:
        # 确保目录存在
        os.makedirs(os.path.dirname(file), exist_ok=True)
        with open(file, "w", encoding="utf-8") as f:
            yaml.safe_dump(data, f, allow_unicode=True)
        print(f"[INFO] 配置已保存到 {file}")
    except Exception as e:
        print(f"[ERROR] 保存 YAML 失败: {e}")

if __name__=="__main__":
    
    args = parse_args()
    setup_logger(args.log_file)
    global_conf = load_conf(args.global_conf,args.conf_encoding)
    camera_conf = load_conf(args.camera_conf,args.conf_encoding)


  # 用字典绑定名字和线程对象
    workers = {
        "detect_worker": threading.Thread(target=detect_worker.work, args=(global_conf, camera_conf), daemon=True),
        "frame_camera_worker": threading.Thread(target=frame_camera_worker.work, args=(global_conf, camera_conf), daemon=True),
        "notify_worker": threading.Thread(target=notify_worker.work, args=(global_conf, camera_conf), daemon=True),
        "alive_worker": threading.Thread(target=alive_worker.work, args=(global_conf, camera_conf), daemon=True),
    }
    status={
        "detect_worker": True,
        "frame_camera_worker":True,
        "notify_worker":True,
        "alive_worker":True, 
    }
    flag=False
    status_file = global_conf["environment"]+camera_conf["status"]
    failed_file = global_conf["environment"]+global_conf["share"]["failed"]["file"]
    failed_lock = global_conf["environment"]+global_conf["share"]["failed"]["lock"]
    failed_conf = global_conf["environment"]+global_conf["share"]["failed"]["conf"]
    lock =FileLock(failed_lock)
    # 启动所有线程
    for name, worker in workers.items():
        worker.start()
        logger.info(f"{name} started")
    logger.info(f"ativated! pid:{os.getpid()}")

    # 周期性检查线程存活
    while True:
        for name, worker in workers.items():
            if worker.is_alive():
                logger.info(f"{name} 正常工作")
            else:
                logger.error(f"{name} 异常退出")
                status[name]=False
                flag=True
        save_to(status,status_file)
        if flag:
            with lock:
                with open(failed_file,"a") as wd:
                   wd.write(f"{os.getpid()}\n")
                with open(failed_conf,"a") as wd:
                   wd.write(f'{global_conf["environment"]+camera_conf["file"]}\n')    
            time.sleep(120)
        time.sleep(30)